# coding=utf-8
# author=haishan09@gmail.com
from django import forms 
from django.forms.formsets import BaseFormSet, formset_factory
from report.models import Report, CutShip, CubeShip
from custom.widgets import JsonifyConfigWidget
from report.configs import CutShipConfig
from dimension import widgets
from dimension.models import Dimension
from common.configs import configmanager


BaseCutShipFormSet = forms.inlineformset_factory(
    Report, 
    CutShip, 
    fields='__all__',
    extra=0,
    can_delete=True
)


class CutShipFormSet(BaseCutShipFormSet):

    def __init__(self, *args, **kwargs):
        super(CutShipFormSet, self).__init__(*args, **kwargs)
        self.instance = kwargs.get('instance')

    def add_fields(self, form, index):
        super(CutShipFormSet, self).add_fields(form, index)
        attrs = {}
        if not form.initial:
            attrs['readonly'] = True
            cut = None
        else:
            cut_pk = form.initial['cut']
            cut = Dimension.objects.get(pk=cut_pk)
        config = CutShipConfig(dim=cut)
        form.fields['config'].widget = JsonifyConfigWidget(config=config, attrs=attrs)

        dimension_choices = []
        if self.instance:
            for ship in self.instance.cubeship_set.all():
                for dimension in ship.cube.dimensions.all():
                    dimension_choice = (dimension.pk, dimension)
                    if not dimension_choice in dimension_choices:
                        dimension_choices.append(dimension_choice)
        form.fields['cut'].widget = forms.Select(choices=dimension_choices)


class CutsForm(forms.Form):

    def __init__(self, report, *args, **kwargs):
        self.report = report
        super(CutsForm, self).__init__(*args, **kwargs)
        self.add_fields()

    def get_field(self, cutship):
        initial = cutship.dconf.get('initial')
        widget_name = cutship.widget.name
        if widget_name == 'TextInput':
            field = forms.CharField(initial=initial, widget=widgets.InputWidget(cutship))
        elif widget_name == 'Choice':
            field = forms.ChoiceField(label=cutship.cut.label,
                                      choices=[(initial, ''), ], 
                                      initial=initial, 
                                      widget=widgets.SelectWidget(cutship))
        elif widget_name == 'MultipleChoice':
            field = forms.MultipleChoiceField(label=cutship.cut.label,
                                              choices=map(lambda c: (c, ''), initial.split(',')), 
                                              initial=initial.split(','),
                                              widget=widgets.SelectMultipleWidget(cutship))
        elif widget_name == 'Date':
            field = forms.CharField(initial=initial, widget=widgets.RangeDateWidget(cutship, attrs={'style': 'width: 180px'}))
        return field

    def add_fields(self):
        for cutship in self.report.cutship_set.all():
            self.fields[cutship.cut.name] = self.get_field(cutship)


class CubeShipForm(forms.ModelForm):

    class Meta:
        model = CubeShip
        exclude = ['config']
        widgets = {
            'label': forms.TextInput(attrs={'class': 'form-control'}),
            'cube': forms.Select(attrs={'class': 'form-control', 'onchange': 'cubechange(this)'}),
            'chart': forms.Select(attrs={'class': 'form-control', 'onchange': 'chartchange(this)'}),
            'limit': forms.NumberInput(attrs={'class': 'form-control'}),
        }


class DrilldownForm(forms.Form):

    def __init__(self, cube=None, *args, **kwargs): 
        choices = [('', '------')]
        self.cube = cube
        if cube:
            choices = choices + [(d.name, d.label) for d in self.cube.dimensions.all()]
        super(DrilldownForm, self).__init__(*args, **kwargs)
        self.fields['drilldown'] = forms.ChoiceField(
            label='', 
            choices=choices,
            required=False,
            widget=forms.Select(attrs={'class': 'can-drilldown form-control', 'onchange': 'drilldownchange(this)'})
        )
        self.fields['rank'] = forms.IntegerField(
            label='', 
            initial=-1,
            required=False,
            widget=forms.HiddenInput(attrs={'class': 'rank can-drilldown form-control'})
        )

class BaseDrilldownFormSet(BaseFormSet):

    def clean(self):
        drilldowns = set()
        duplicates = False
        for form in self.forms:
            if form.cleaned_data:
                drilldown = form.cleaned_data.get('drilldown')
                if not drilldown:
                    continue
                if drilldown in drilldowns:
                    duplicates = True
                else:
                    drilldowns.add(drilldown)
        if duplicates:
            raise forms.ValidationError('选择的分组不可重复!', code='duplicate_drilldowns')


DrilldownFormSet = formset_factory(DrilldownForm, formset=BaseDrilldownFormSet, max_num=6)

class CutForm(forms.Form):

    def __init__(self, cube=None, cut=None, *args, **kwargs): 
        choices = [('', '------')]
        self.cube = cube
        if cube:
            choices = choices + \
                    [(d.name, d.label) for d in self.cube.dimensions.all()] + \
                    [(d.name, d.label) for d in self.cube.aggregates.all()]
        super(CutForm, self).__init__(*args, **kwargs)
        self.fields['cut'] = forms.ChoiceField(
            label='', 
            choices=choices,
            required=False,
            widget=forms.Select(attrs={'class': 'can-cut form-control', 'onchange': 'cutchange(this)'})
        )
        self.fields['condition'] = forms.ChoiceField(
            label='', 
            choices=[
                ('eq', '等于'), 
                ('neq', '不等于'),
                ('lt', '小于'),
                ('lte', '小于等于'),
                ('gt', '大于'),
                ('gte', '大于等于'),
            ],
            required=False,
            widget=forms.Select(attrs={'class': 'can-cut form-control'})
        )
        if self.initial.get('cut'):
            cut = Dimension.objects.get(name=self.initial['cut'])
            self.fields['value'] = forms.ChoiceField(
                label='', 
                choices=cut.get_choices(),
                required=False,
                widget=forms.Select(attrs={'class': 'can-cut form-control'})
            )
        else:
            self.fields['value'] = forms.CharField(
                label='', 
                required=False,
                widget=forms.TextInput(attrs={'class': 'can-cut form-control'})
            )
        self.fields['rank'] = forms.IntegerField(
            label='', 
            initial=0,
            required=False,
            widget=forms.HiddenInput(attrs={'class': 'rank can-cut form-control'})
        )

class BaseCutFormSet(BaseFormSet):

    def clean(self):
        cuts = set()
        duplicates = False
        for form in self.forms:
            if form.cleaned_data:
                cut = form.cleaned_data.get('cut')
                if not cut:
                    continue
                if cut in cuts:
                    duplicates = True
                else:
                    cuts.add(cut)
        if duplicates:
            raise forms.ValidationError('选择的筛选项不可重复!', code='duplicate_cuts')


CutFormSet = formset_factory(CutForm, formset=BaseCutFormSet, max_num=4)

class AggregateForm(forms.Form):

    def __init__(self, cube=None, chart=None, *args, **kwargs): 
        choices = [('', '------')]
        self.cube = cube
        self.chart = chart
        if cube:
            choices = choices + [(d.name, d.label) for d in self.cube.aggregates.all()]
        super(AggregateForm, self).__init__(*args, **kwargs)
        self.fields['aggregate'] = forms.ChoiceField(
            label='', 
            choices=choices,
            required=False,
            widget=forms.Select(attrs={'class': 'form-control'})
        )
        if self.chart and self.chart.name in ('line', 'bar'):
            self.fields['chart_type'] = forms.ChoiceField(
                label='', 
                choices=[('', '------'), ('line', '线性'), ('bar', '柱状')],
                required=False,
                initial=self.chart.name,
                widget=forms.Select(attrs={'class': 'slide-toggle form-control'})
            )
            self.fields['yaxis_index'] = forms.ChoiceField(
                label='', 
                choices=[('1eft', 'Y.0'), ('right', 'Y.1')],
                required=False,
                widget=forms.Select(attrs={'class': 'slide-toggle form-control'})
            )
            self.fields['stack'] = forms.CharField(
                label='', 
                required=False,
                widget=forms.TextInput(attrs={'placeholder': 'stack', 'class': 'slide-toggle form-control'})
            )
        self.fields['expression'] = forms.CharField(
            label='', 
            required=False,
            widget=forms.Textarea(attrs={'class': 'slide-toggle form-control', 
                                         'rows': 3,
                                         'placeholder': 'lambda 表达式'})
        )
        self.fields['rank'] = forms.IntegerField(
            label='', 
            initial=0,
            required=False,
            widget=forms.HiddenInput(attrs={'class': 'rank form-control'})
        )

class BaseAggregateFormSet(BaseFormSet):
    pass

AggregateFormSet = formset_factory(AggregateForm, formset=BaseAggregateFormSet)


class OrderByForm(forms.Form):

    def __init__(self, cube=None, *args, **kwargs): 
        choices = [('', '------')]
        self.cube = cube
        if cube:
            choices = choices + \
                    [(d.name, d.label) for d in self.cube.dimensions.all()] + \
                    [(d.name, d.label) for d in self.cube.aggregates.all()]
        super(OrderByForm, self).__init__(*args, **kwargs)
        self.fields['order_by'] = forms.ChoiceField(
            label='', 
            choices=choices,
            required=False,
            widget=forms.Select(attrs={'class': 'can-order form-control'})
        )
        self.fields['order'] = forms.ChoiceField(
            label='', 
            choices=[('', '------'), ('asc', '顺序'), ('desc', '倒序')],
            required=False,
            widget=forms.Select(attrs={'class': 'form-control'})
        )
        self.fields['rank'] = forms.IntegerField(
            label='', 
            initial=0,
            required=False,
            widget=forms.HiddenInput(attrs={'class': 'rank form-control'})
        )


class BaseOrderByFormSet(BaseFormSet):

    def clean(self):
        order_bys = set()
        duplicates = False
        for form in self.forms:
            if form.cleaned_data:
                order_by = form.cleaned_data.get('order_by')
                if not order_by:
                    continue
                if order_by in order_bys:
                    duplicates = True
                else:
                    order_bys.add(order_by)
        if duplicates:
            raise forms.ValidationError('选择的排序项不可重复!', code='duplicate_orderbys')


OrderByFormSet = formset_factory(OrderByForm, formset=BaseOrderByFormSet, max_num=2)


class ChartConfigForm(forms.Form):

    def __init__(self, *args, **kwargs): 
        self.chart = kwargs.pop('chart')
        chart_name = self.chart and self.chart.name or None
        super(ChartConfigForm, self).__init__(*args, **kwargs)
        self.fields['config'] = forms.CharField(
            label='', 
            required=False,
            widget=JsonifyConfigWidget(
                configmanager.get_config('chart', chart_name)(), 
                attrs={'class': 'form-control'})
            )
